home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / mus / edit / AlgoRhythms.lha / AlgoRhythms / Source / musicrexx.c < prev    next >
C/C++ Source or Header  |  1994-11-25  |  30KB  |  818 lines

  1. /* musicrexx.c
  2.     Copyright (c) 1993 by Thomas E. Janzen
  3.     All Rights Reserved
  4.  
  5.     THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
  6.     BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
  7.     CHANGES FOR FREE DISTRIBUTION.  NO TITLE TO AND OWNERSHIP OF THE
  8.     SOFTWARE IS HEREBY TRANSFERRED.  THOMAS E. JANZEN ASSUMES NO 
  9.     RESPONSIBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
  10.     
  11.     Thomas E. Janzen
  12.     208A Olde Derby Road
  13.     Norwood, MA  02062-1761
  14.     (617)769-7733
  15.  
  16. **  FACILITY:
  17. **
  18. **    AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
  19. **    compiled with SAS/C Amiga Compiler 6.50 
  20. **
  21. **  ABSTRACT:
  22. **
  23. **    musicrexx.c support Arexx for AlgoRhythms.
  24. **
  25. **  AUTHORS: Thomas E. Janzen
  26. **
  27. **  CREATION DATE:    23-OCT-1993
  28. **
  29. **  MODIFICATION HISTORY:
  30. **    DATE    NAME    DESCRIPTION
  31. **   1 JAN 94 TEJ     New for V3.0
  32. **-- 
  33. */
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <devices/timer.h>
  39. #include <math.h>
  40. #include <clib/intuition_protos.h>
  41. #include <proto/exec.h>
  42. #include "arexx.h"
  43. #include "arexxsyslib.h"
  44. #include "musicrexx.h"
  45. #include "scales.h"
  46. #include "drawform.h"
  47. #include "window.h"
  48. #include "files.h"
  49. #include "pitchnames.h"
  50.  
  51. #define DEFAULT_NAME  "ALGORHYTHMS"
  52. #define REPLY_STR     "AlgoRhythms Acknowledge"
  53. #define REPLY_LEN     (sizeof(REPLY_STR))
  54. #define C_NAME_LEN    80
  55. #define C_MAX_TRIES   99
  56. #define CMD_STR_LEN   128
  57.  
  58.  
  59. #define BREAK_CHARS " \t"
  60. #define MAX_TOKEN_QTY (10)
  61. /*
  62. ** Tokens for the Arexx command language
  63. */
  64. #define M_MENU      (0XF)
  65. #define M_ITEM      (0XF0)
  66. #define M_SUBITEM   (0XF00)
  67. #define M_SUBSUBITEM (0XF000)
  68.  
  69. #define S_PROJECT   "PROJECT"
  70. #define N_PROJECT   (0X1)
  71. #define S_PLAY      "PLAY"
  72. #define N_PLAY      (0X10)
  73. #define S_STOP      "STOP"
  74. #define N_STOP      (0X20)
  75. #define S_CONTINUE  "CONTINUE"
  76. #define N_CONTINUE  (0X30)
  77. #define S_LOADFORM  "LOADFORM"
  78. #define N_LOADFORM  (0X40)
  79. #define S_SAVEFORM  "SAVEFORM"
  80. #define N_SAVEFORM  (0X50)
  81. #define S_RECORD    "RECORD"
  82. #define N_RECORD    (0X60)
  83. #define S_ON        "ON"
  84. #define N_ON        (0X100)
  85. #define S_OFF       "OFF"
  86. #define N_OFF       (0X200)
  87. #define S_ERASE     "ERASE"
  88. #define N_ERASE     (0X70)
  89. #define S_LOAD8SVX  "LOAD8SVX"
  90. #define N_LOAD8SVX  (0X80)
  91. #define S_SAVEMIDI  "SAVEMIDI"
  92. #define N_SAVEMIDI  (0X90)
  93. #define S_QUIT      "QUIT"
  94. #define N_QUIT      (0XA0)
  95. #define S_FORM      "FORM"
  96. #define N_FORM      (0X2)
  97. #define S_MAXVOICES "MAXVOICES"
  98. #define N_MAXVOICES (0X10)
  99. #define S_REDRAW    "REDRAW"
  100. #define N_REDRAW    (0X20)
  101. #define S_PULSE     "PULSE"
  102. #define N_PULSE     (0X30)
  103. #define S_DURATION  "DURATION"
  104. #define N_DURATION  (0X40)
  105. #define S_PITCH     "PITCH"
  106. #define N_PITCH     (0X50)
  107. #define S_MEAN      "MEAN"
  108. #define N_MEAN      (0X100)
  109. #define S_RANGE     "RANGE"
  110. #define N_RANGE     (0X200)
  111. #define S_PERIOD    "PERIOD"
  112. #define N_PERIOD    (0X1000)
  113. #define S_PHASE     "PHASE"
  114. #define N_PHASE     (0X2000)
  115. #define S_RANDOMIZE "RANDOMIZE"
  116. #define N_RANDOMIZE (0X300)
  117. #define S_RHYTHM    "RHYTHM"
  118. #define N_RHYTHM    (0X60)
  119. #define S_DYNAMIC   "DYNAMIC"
  120. #define N_DYNAMIC   (0X70)
  121. #define S_TEXTURE   "TEXTURE"
  122. #define N_TEXTURE   (0X80)
  123. #define S_NOTELENGTH "NOTELENGTH"
  124. #define N_NOTELENGTH (0X90)
  125. #define S_MAXIMUM   "MAXIMUM"
  126. #define N_MAXIMUM   (0X100)
  127. #define S_MINIMUM   "MINIMUM"
  128. #define N_MINIMUM   (0X200)
  129. #define S_SCALE     "SCALE"
  130. #define N_SCALE     (0X3)
  131. #define S_TRANSPOSE "TRANSPOSE"
  132. #define N_TRANSPOSE (0X0)
  133. #define S_PENTATONIC "PENTATONIC"
  134. #define N_PENTATONIC (0X10)
  135. #define S_SHORTPENTATONIC "SHORTPENTATONIC"
  136. #define N_SHORTPENTATONIC (0X20)
  137. #define S_HARMONIC  "HARMONIC"
  138. #define N_HARMONIC  (0X30)
  139. #define S_DIATONIC  "DIATONIC"
  140. #define N_DIATONIC  (0X40)
  141. #define S_HIRAJOSHI "HIRAJOSHI"
  142. #define N_HIRAJOSHI (0X50)
  143. #define S_KUMOIJOSHI "KUMOIJOSHI"
  144. #define N_KUMOIJOSHI (0X60)
  145. #define S_KOKINJOSHI "KOKINJOSHI"
  146. #define N_KOKINJOSHI (0X70)
  147. #define S_WHOLETONE "WHOLETONE"
  148. #define N_WHOLETONE (0X80)
  149. #define S_QUINTAL "QUINTAL"
  150. #define N_QUINTAL (0X90)
  151. #define S_MIN3MAJ2 "MIN3MAJ2"
  152. #define N_MIN3MAJ2 (0XA0)
  153. #define S_HARMONICMINOR "HARMONICMINOR"
  154. #define N_HARMONICMINOR (0XB0)
  155. #define S_HUNGARIANMINOR "HUNGARIANMINOR"
  156. #define N_HUNGARIANMINOR (0XC0)
  157. #define S_DIMINISHED "DIMINISHED"
  158. #define N_DIMINISHED (0XD0)
  159. #define S_MODE3 "MODE3"
  160. #define N_MODE3 (0XE0)
  161. #define S_MODE4 "MODE4"
  162. #define N_MODE4 (0XF0)
  163. #define S_MODE5 "MODE5"
  164. #define N_MODE5 (0X100)
  165. #define S_MODE6 "MODE6"
  166. #define N_MODE6 (0X110)
  167. #define S_MODE7 "MODE7"
  168. #define N_MODE7 (0X120)
  169. #define S_QUARTAL "QUARTAL"
  170. #define N_QUARTAL (0X130)
  171. #define S_MAJ3MIN2 "MAJ3MIN2"
  172. #define N_MAJ3MIN2 (0X140)
  173. #define S_CHROMATIC "CHROMATIC"
  174. #define N_CHROMATIC (0X150)
  175. #define S_VOICE     "VOICE"
  176. #define N_VOICE     (0X4)
  177. #define S_CHANNEL   "CHANNEL"
  178. #define N_CHANNEL   (0X10)
  179. #define S_LOWNOTE   "LOWNOTE"
  180. #define N_LOWNOTE   (0X20)
  181. #define S_HIGHNOTE  "HIGHNOTE"
  182. #define N_HIGHNOTE  (0X30)
  183. #define S_WALKING   "WALKING"
  184. #define N_WALKING   (0X40)
  185. #define S_RANDOM    "RANDOM"
  186. #define N_RANDOM    (0X50)
  187. #define S_AUDIO     "AUDIO"
  188. #define N_AUDIO     (0X60)
  189. #define S_MIDI      "MIDI"
  190. #define N_MIDI      (0X70)
  191.  
  192. typedef struct token_struct TOKEN_TYPE;
  193. struct token_struct
  194. {
  195.     char *token_str;
  196.     int token_num;
  197. };
  198.  
  199. #define C_TOKEN_QTY (61)
  200.  
  201. static TOKEN_TYPE tokens[] =
  202.     {{S_PROJECT, N_PROJECT},
  203.     {S_PLAY, N_PLAY},
  204.     {S_STOP, N_STOP},
  205.     {S_CONTINUE, N_CONTINUE},
  206.     {S_LOADFORM, N_LOADFORM},
  207.     {S_SAVEFORM, N_SAVEFORM},
  208.     {S_RECORD, N_RECORD},
  209.     {S_ON, N_ON},
  210.     {S_OFF, N_OFF},
  211.     {S_ERASE, N_ERASE},
  212.     {S_LOAD8SVX, N_LOAD8SVX},
  213.     {S_SAVEMIDI, N_SAVEMIDI},
  214.     {S_QUIT, N_QUIT},
  215.     {S_FORM, N_FORM},
  216.     {S_MAXVOICES, N_MAXVOICES},
  217.     {S_REDRAW, N_REDRAW},
  218.     {S_PULSE, N_PULSE},
  219.     {S_DURATION, N_DURATION},
  220.     {S_PITCH, N_PITCH},
  221.     {S_MEAN, N_MEAN},
  222.     {S_RANGE, N_RANGE},
  223.     {S_PERIOD, N_PERIOD},
  224.     {S_PHASE, N_PHASE},
  225.     {S_RANDOMIZE, N_RANDOMIZE},
  226.     {S_RHYTHM, N_RHYTHM},
  227.     {S_DYNAMIC, N_DYNAMIC},
  228.     {S_TEXTURE, N_TEXTURE},
  229.     {S_NOTELENGTH, N_NOTELENGTH},
  230.     {S_MAXIMUM, N_MAXIMUM},
  231.     {S_MINIMUM, N_MINIMUM},
  232.     {S_SCALE, N_SCALE},
  233.     {S_TRANSPOSE, N_TRANSPOSE},
  234.     {S_PENTATONIC, N_PENTATONIC},
  235.     {S_SHORTPENTATONIC, N_SHORTPENTATONIC},
  236.     {S_HARMONIC, N_HARMONIC},
  237.     {S_DIATONIC, N_DIATONIC},
  238.     {S_HIRAJOSHI, N_HIRAJOSHI},
  239.     {S_KUMOIJOSHI, N_KUMOIJOSHI},
  240.     {S_KOKINJOSHI, N_KOKINJOSHI},
  241.     {S_WHOLETONE, N_WHOLETONE},
  242.     {S_QUINTAL, N_QUINTAL},
  243.     {S_MIN3MAJ2, N_MIN3MAJ2},
  244.     {S_HARMONICMINOR, N_HARMONICMINOR},
  245.     {S_HUNGARIANMINOR, N_HUNGARIANMINOR},
  246.     {S_DIMINISHED, N_DIMINISHED},
  247.     {S_MODE3, N_MODE3},
  248.     {S_MODE4, N_MODE4},
  249.     {S_MODE5, N_MODE5},
  250.     {S_MODE6, N_MODE6},
  251.     {S_MODE7, N_MODE7},
  252.     {S_QUARTAL, N_QUARTAL},
  253.     {S_MAJ3MIN2, N_MAJ3MIN2},
  254.     {S_CHROMATIC, N_CHROMATIC},
  255.     {S_VOICE, N_VOICE},
  256.     {S_CHANNEL, N_CHANNEL},
  257.     {S_LOWNOTE, N_LOWNOTE},
  258.     {S_HIGHNOTE, N_HIGHNOTE},
  259.     {S_WALKING, N_WALKING},
  260.     {S_RANDOM, N_RANDOM},
  261.     {S_AUDIO, N_AUDIO},
  262.     {S_MIDI, N_MIDI}};
  263.  
  264. struct MsgPort *rexx_port   = NULL;
  265. extern ULONG g_rexx_fubar = 0L;
  266. static char port_name[C_NAME_LEN];
  267.  
  268. static struct MsgPort *register_port(LONG pri );
  269.  
  270.  
  271. static struct MsgPort *register_port(LONG pri)
  272. {
  273.     auto int name_index = 0;    
  274.     auto struct MsgPort *port = NULL;
  275.  
  276.     Forbid();
  277.     do
  278.     {
  279.         sprintf(port_name, "%s_%d", DEFAULT_NAME, name_index);
  280.         name_index++;
  281.     } while ((FindPort(port_name) != NULL) && (name_index < C_MAX_TRIES));
  282.     port = CreateMsgPort();
  283.     port->mp_Node.ln_Name = port_name;
  284.     port->mp_Node.ln_Pri = pri;
  285.     AddPort(port);
  286.  
  287.     Permit();
  288.     return port;
  289. }
  290.  
  291. void shut_rexx(void)
  292. {
  293.     auto struct RexxMsg *rexx_msg;
  294.  
  295.     if (rexx_port != NULL)
  296.     {
  297.         Forbid();
  298.     }
  299.     while((rexx_msg = (struct RexxMsg *)GetMsg(rexx_port)) != NULL)
  300.     {
  301.         rexx_msg->rm_Result1 = RC_FATAL;
  302.         rexx_msg->rm_Result2 = NULL;
  303.         ReplyMsg( (struct Message *) rexx_msg );
  304.     }
  305.     RemPort(rexx_port);
  306.     DeleteMsgPort(rexx_port);
  307.     Permit();
  308.  
  309.     if( RexxSysBase )
  310.     {
  311.         CloseLibrary( RexxSysBase );
  312.     }
  313.     return;
  314. }
  315.  
  316. static int parse_rexx( struct RexxMsg *msg, FORM_TYPE *form,
  317.                   struct timeval *duration, int *tempo, 
  318.                   NOTE_EVENT_TYPE *events, NOTE_LEN_TYPE *note_len,
  319.                   int *max_voices, int *scale, int *range,
  320.                   int *half_range, int *delay_ticks);
  321.  
  322. ULONG rexx_mask = 0L;
  323.  
  324. void init_rexx(void)
  325. {
  326.     RexxSysBase = OpenLibrary( (UBYTE *) "rexxsyslib.library", 0L );
  327.     if(NULL == RexxSysBase)
  328.     {
  329.         g_rexx_fubar = 1;
  330.     }
  331.     if (!g_rexx_fubar)
  332.     {
  333.         /* Create a port. */
  334.         rexx_port = register_port(1L);
  335.         if(NULL == rexx_port)
  336.         {
  337.             g_rexx_fubar = 1;
  338.         }
  339.         else
  340.         {
  341.             rexx_mask = (1L << rexx_port->mp_SigBit);
  342.         }
  343.     }
  344.     return;
  345. }
  346.  
  347. int process_rexx(FORM_TYPE *form,
  348.                   struct timeval *duration, int *tempo, 
  349.                   NOTE_EVENT_TYPE *events, NOTE_LEN_TYPE *note_len,
  350.                   int *max_voices, int *scale, int *range,
  351.                   int *half_range, int *delay_ticks)
  352. {
  353.     auto struct RexxMsg *rexx_msg;
  354.     auto int result = 0;
  355.  
  356.     while((rexx_msg = (struct RexxMsg *) GetMsg(rexx_port)) != NULL)
  357.     {
  358.         result = 1;
  359.         result = parse_rexx(rexx_msg, form, duration, tempo, events, 
  360.                             note_len, max_voices, scale, range,
  361.                             half_range, delay_ticks);
  362.         ReplyMsg((struct Message *)rexx_msg);
  363.     }
  364.     return result;
  365. }
  366.  
  367. static int parse_rexx(struct RexxMsg *rexx_msg, FORM_TYPE *form,
  368.                   struct timeval *duration, int *tempo, 
  369.                   NOTE_EVENT_TYPE *events, NOTE_LEN_TYPE *note_len,
  370.                   int *max_voices, int *scale, int *range,
  371.                   int *half_range, int *delay_ticks)
  372. {
  373.     auto ULONG  action_code;
  374.     auto char   cmd_str[CMD_STR_LEN],
  375.                 *chr,
  376.                 break_str[] = BREAK_CHARS;
  377.     auto int token_counter,
  378.              token_counter_inner,
  379.                 token_accum,
  380.                 token_qty,
  381.                 compare,
  382.                 temp_num,
  383.                 transpose_interval,
  384.                 sts,
  385.                 voice_num,
  386.                 result = 0; /* must be automatic */
  387.     auto TOKEN_TYPE actual_tokens[MAX_TOKEN_QTY];
  388.  
  389.     action_code = rexx_msg->rm_Action & RXCODEMASK;
  390.  
  391.     if(RXCOMM == action_code)
  392.     {
  393.         strcpy(cmd_str, rexx_msg->rm_Args[0]);
  394.         /*
  395.         ** pre-process the command
  396.         */
  397.         for (chr = cmd_str; *chr != '\0'; chr++)
  398.         {
  399.             *chr = toupper(*chr);
  400.         }
  401.         token_qty = 0;
  402.         actual_tokens[token_qty].token_str 
  403.             = strtok(cmd_str, break_str);
  404.         if (actual_tokens[0].token_str != NULL)
  405.         {
  406.             do
  407.             {
  408.                 token_qty++;   
  409.             } while ((NULL !=
  410.                 (actual_tokens[token_qty].token_str 
  411.                 = strtok((char *)NULL, break_str))) 
  412.                 && (token_qty < MAX_TOKEN_QTY));
  413.         }
  414.         /*
  415.         ** This is a cross product.  there is a better way
  416.         ** It doesn't recognique order differences.
  417.         */
  418.         token_accum = 0;
  419.         for (   token_counter = 0; token_counter < C_TOKEN_QTY;
  420.                 token_counter++)
  421.         {
  422.             for (token_counter_inner = 0; token_counter_inner <
  423.                     token_qty; token_counter_inner++)
  424.             {
  425.                 compare = strcmp(tokens[token_counter].token_str,
  426.                     actual_tokens[token_counter_inner].token_str);
  427.                 if (0 == compare)
  428.                 {
  429.                     token_accum |= tokens[token_counter].token_num;
  430.                 }
  431.             }
  432.         }
  433.         switch (token_accum & M_MENU)
  434.         {
  435.             case N_PROJECT:
  436.                 switch (token_accum & M_ITEM)
  437.                 {
  438.                     case N_PLAY:
  439.                         result = C_REXX_PLAY;
  440.                         break;
  441.                     case N_STOP:
  442.                         result = C_REXX_STOP;
  443.                         break;
  444.                     case N_CONTINUE:
  445.                         result = C_REXX_CONTINUE;
  446.                         break;
  447.                     case N_LOADFORM:
  448.                         sts 
  449.                         = read_file(actual_tokens[2].token_str, 
  450.                         duration, range,
  451.                           scale, max_voices, tempo, form, events,note_len);
  452.                         if (!sts) 
  453.                         {
  454.                             if (0 == *tempo) 
  455.                             {
  456.                                 *delay_ticks = 0;
  457.                             }
  458.                             else 
  459.                             {
  460.                                 *delay_ticks = 50 / (*tempo);
  461.                             }
  462.                             *half_range = *range / 2;
  463.                             draw_form(duration, form);
  464. #if 0
  465.                             SetWindowTitles(w, actual_tokens[2].token_str, 
  466.                             (void *) -1L);
  467. #endif
  468.                             result = C_REXX_CHANG_BOTH;
  469.                         }
  470.                         break;
  471.                     case N_SAVEFORM:
  472.                         break;
  473.                     case N_RECORD:
  474.                         switch (token_accum & M_SUBITEM)
  475.                         {
  476.                             case N_ON:
  477.                                 break;
  478.                             case N_OFF:
  479.                                 break;
  480.                         }
  481.                     case N_ERASE:
  482.                         break;
  483.                     case N_LOAD8SVX:
  484.                         break;
  485.                     case N_SAVEMIDI:
  486.                         break;
  487.                     case N_QUIT:
  488.                         break;
  489.                 }
  490.                 break;
  491.             case N_FORM:
  492.                 switch (token_accum & M_ITEM)
  493.                 {
  494.                     case N_MAXVOICES:
  495.                         *max_voices 
  496.                         = strtoul(actual_tokens[2].token_str, 
  497.                         (char **)NULL, 10L) 
  498.                         % 20;
  499.                         result = C_REXX_CHANG_FORM;
  500.                         break;
  501.                     case N_REDRAW:
  502.                         draw_form(duration, form);
  503.                         break;
  504.                     case N_PULSE:
  505.                         *tempo 
  506.                             = strtoul(actual_tokens[2].token_str, 
  507.                             (char **)NULL, 10L) % 25;
  508.                         if (*tempo != 0)
  509.                         {
  510.                             *delay_ticks = 50 / *tempo;
  511.                         }
  512.                         else
  513.                         {
  514.                             *delay_ticks = 0;
  515.                         }
  516.                         result = C_REXX_CHANG_FORM;
  517.                         break;
  518.                     case N_DURATION:
  519.                         duration->tv_secs
  520.                             = strtoul(actual_tokens[2].token_str, 
  521.                             (char **)NULL, 10L);
  522.                         duration->tv_micro = 0;
  523.                         result = C_REXX_CHANG_FORM;
  524.                         break;
  525.                     case N_PITCH:
  526.                         switch (token_accum & M_SUBITEM)
  527.                         {
  528.                             case N_MEAN:
  529.                                 switch (token_accum & M_SUBSUBITEM)
  530.                                 {
  531.                                     case N_PERIOD:
  532.                                         form->frm_s_pitch.prm_d_mean_cycle 
  533.                                           = strtod(actual_tokens[4]
  534.                                           .token_str, (char **)NULL);
  535.                                         result = C_REXX_CHANG_FORM;
  536.                                         break;
  537.                                     case N_PHASE:
  538.                                         form->frm_s_pitch.prm_d_mean_phase 
  539.                                         = strtod(actual_tokens[4]
  540.                                         .token_str, (char **)NULL);
  541.                                         result = C_REXX_CHANG_FORM;
  542.                                         break;
  543.                                 }
  544.                                 break;
  545.                             case N_RANGE:
  546.                                 switch (token_accum & M_SUBSUBITEM)
  547.                                 {
  548.                                     case N_PERIOD:
  549.                                         form->frm_s_pitch.prm_d_range_cycle
  550.                                         = strtod(actual_tokens[4]
  551.                                         .token_str, (char **)NULL);
  552.                                         result = C_REXX_CHANG_FORM;
  553.                                         break;
  554.                                     case N_PHASE:
  555.                                         form->frm_s_pitch.prm_d_range_phase
  556.                                         = strtod(actual_tokens[4]
  557.                                         .token_str, (char **)NULL);
  558.                                         result = C_REXX_CHANG_FORM;
  559.                                         break;
  560.                                 }
  561.                                 break;
  562.                             case N_RANDOMIZE:
  563.                                 randomize_parameter(&form->frm_s_pitch);
  564.                                 result = C_REXX_CHANG_FORM;
  565.                                 break;
  566.                         }
  567.                     case N_RHYTHM:
  568.                         switch (token_accum & M_SUBITEM)
  569.                         {
  570.                             case N_MEAN:
  571.                                 switch (token_accum & M_SUBSUBITEM)
  572.                                 {
  573.                                     case N_PERIOD:
  574.                                         form->frm_s_rhythm.prm_d_mean_cycle
  575.                                           = strtod(actual_tokens[4]
  576.                                           .token_str, (char **)NULL);
  577.                                         result = C_REXX_CHANG_FORM;
  578.                                         break;
  579.                                     case N_PHASE:
  580.                                         form->frm_s_rhythm.prm_d_mean_phase
  581.                                         = strtod(actual_tokens[4]
  582.                                         .token_str, (char **)NULL);
  583.                                         result = C_REXX_CHANG_FORM;
  584.                                         break;
  585.                                 }
  586.                                 break;
  587.                             case N_RANGE:
  588.                                 switch (token_accum & M_SUBSUBITEM)
  589.                                 {
  590.                                     case N_PERIOD:
  591.                                         form->frm_s_rhythm
  592.                                         .prm_d_range_cycle 
  593.                                         = strtod(actual_tokens[4]
  594.                                         .token_str, (char **)NULL);
  595.                                         result = C_REXX_CHANG_FORM;
  596.                                         break;
  597.                                     case N_PHASE:
  598.                                         form->frm_s_rhythm
  599.                                         .prm_d_range_phase 
  600.                                         = strtod(actual_tokens[4]
  601.                                         .token_str, (char **)NULL);
  602.                                         result = C_REXX_CHANG_FORM;
  603.                                         break;
  604.                                 }
  605.                                 break;
  606.                             case N_RANDOMIZE:
  607.                                 randomize_parameter(&form->frm_s_rhythm);
  608.                                 result = C_REXX_CHANG_FORM;
  609.                                 break;
  610.                         }
  611.                     case N_DYNAMIC:
  612.                         switch (token_accum & M_SUBITEM)
  613.                         {
  614.                             case N_MEAN:
  615.                                 switch (token_accum & M_SUBSUBITEM)
  616.                                 {
  617.                                     case N_PERIOD:
  618.                                         form->frm_s_dynamic
  619.                                         .prm_d_mean_cycle 
  620.                                           = strtod(actual_tokens[4]
  621.                                           .token_str, (char **)NULL);
  622.                                         result = C_REXX_CHANG_FORM;
  623.                                         break;
  624.                                     case N_PHASE:
  625.                                         form->frm_s_dynamic
  626.                                         .prm_d_mean_phase 
  627.                                         = strtod(actual_tokens[4]
  628.                                         .token_str, (char **)NULL);
  629.                                         result = C_REXX_CHANG_FORM;
  630.                                         break;
  631.                                 }
  632.                                 break;
  633.                             case N_RANGE:
  634.                                 switch (token_accum & M_SUBSUBITEM)
  635.                                 {
  636.                                     case N_PERIOD:
  637.                                         form->frm_s_dynamic
  638.                                         .prm_d_range_cycle 
  639.                                         = strtod(actual_tokens[4]
  640.                                         .token_str, (char **)NULL);
  641.                                         result = C_REXX_CHANG_FORM;
  642.                                         break;
  643.                                     case N_PHASE:
  644.                                         form->frm_s_dynamic
  645.                                         .prm_d_range_phase 
  646.                                         = strtod(actual_tokens[4]
  647.                                         .token_str, (char **)NULL);
  648.                                         result = C_REXX_CHANG_FORM;
  649.                                         break;
  650.                                 }
  651.                                 break;
  652.                             case N_RANDOMIZE:
  653.                                 randomize_parameter(&form->frm_s_dynamic);
  654.                                 result = C_REXX_CHANG_FORM;
  655.                                 break;
  656.                         }
  657.                     case N_TEXTURE:
  658.                         switch (token_accum & M_SUBITEM)
  659.                         {
  660.                             case N_RANGE:
  661.                                 switch (token_accum & M_SUBSUBITEM)
  662.                                 {
  663.                                     case N_PERIOD:
  664.                                         form->frm_s_texture
  665.                                         .prm_d_range_cycle 
  666.                                         = strtod(actual_tokens[4]
  667.                                         .token_str, (char **)NULL);
  668.                                         result = C_REXX_CHANG_FORM;
  669.                                         break;
  670.                                     case N_PHASE:
  671.                                         form->frm_s_texture
  672.                                         .prm_d_range_phase 
  673.                                         = strtod(actual_tokens[4]
  674.                                         .token_str, (char **)NULL);
  675.                                         result = C_REXX_CHANG_FORM;
  676.                                         break;
  677.                                 }
  678.                                 break;
  679.                             case N_RANDOMIZE:
  680.                                 randomize_parameter(&form->frm_s_texture);
  681.                                 result = C_REXX_CHANG_FORM;
  682.                                 break;
  683.                         }
  684.                         break;
  685.                     case N_NOTELENGTH:
  686.                         switch (token_accum & M_SUBITEM)
  687.                         {
  688.                             case N_MAXIMUM:
  689.                                 note_len->len_i_max = (int)floor(strtod
  690.                                 (actual_tokens[3].token_str, 
  691.                                 (char **)NULL) * 1000.0);
  692.                                 result = C_REXX_CHANG_FORM;
  693.                                 break;
  694.                             case N_MINIMUM:
  695.                                 note_len->len_i_min = (int)floor(strtod
  696.                                 (actual_tokens[3].token_str, 
  697.                                 (char **)NULL) * 1000.0);
  698.                                 result = C_REXX_CHANG_FORM;
  699.                                 break;
  700.                         }
  701.                 }
  702.                 break;
  703.             case N_VOICE:
  704.                 switch (token_accum & M_ITEM)
  705.                 {
  706.                     case N_CHANNEL:
  707.                         voice_num 
  708.                         = strtoul(actual_tokens[1].token_str, 
  709.                         (char **)NULL, 10L) - 1;
  710.                         if ((voice_num < MAXVOICE) && (voice_num >= 0))
  711.                         {
  712.                             events[voice_num].nv_i_channel = 
  713.                             strtoul(actual_tokens[3].token_str, 
  714.                             (char **)NULL, 10L);
  715.                         }
  716.                         result = C_REXX_CHANG_VOICE;
  717.                         break;
  718.                     case N_LOWNOTE:
  719.                         voice_num 
  720.                         = strtoul(actual_tokens[1].token_str, 
  721.                         (char **)NULL, 10L) - 1;
  722.                         if ((voice_num < MAXVOICE) && (voice_num >= 0))
  723.                         {
  724.                             events[voice_num].nv_i_low_pitch 
  725.                             = pitch_to_midi(actual_tokens[3].token_str);
  726.                         }
  727.                         result = C_REXX_CHANG_VOICE;
  728.                         break;
  729.                     case N_HIGHNOTE:
  730.                         voice_num 
  731.                             = strtoul(actual_tokens[1].token_str, 
  732.                             (char **)NULL, 10L) - 1;
  733.                             if ((voice_num < MAXVOICE) && (voice_num >= 0))
  734.                         {
  735.                             events[voice_num].nv_i_high_pitch 
  736.                             = pitch_to_midi(actual_tokens[3].token_str);
  737.                         }
  738.                         result = C_REXX_CHANG_VOICE;
  739.                         break;
  740.                     case N_WALKING:
  741.                         voice_num 
  742.                             = strtoul(actual_tokens[1].token_str, 
  743.                             (char **)NULL, 10L) - 1;
  744.                             if ((voice_num < MAXVOICE) && (voice_num >= 0))
  745.                         {
  746.                             events[voice_num].nv_i_walking = 1;
  747.                         }
  748.                         result = C_REXX_CHANG_VOICE;
  749.                         break;
  750.                     case N_RANDOM:
  751.                         voice_num 
  752.                             = strtoul(actual_tokens[1].token_str, 
  753.                             (char **)NULL, 10L) - 1;
  754.                         if ((voice_num < MAXVOICE) && (voice_num >= 0))
  755.                         {
  756.                             events[voice_num].nv_i_walking = 0;
  757.                         }
  758.                         result = C_REXX_CHANG_VOICE;
  759.                         break;
  760.                     case N_AUDIO:
  761.                         voice_num 
  762.                             = strtoul(actual_tokens[1].token_str, 
  763.                             (char **)NULL, 10L) - 1;
  764.                         if ((voice_num < MAXVOICE) && (voice_num >= 0))
  765.                         {
  766.                             events[voice_num].nv_i_audio = 1;
  767.                         }
  768.                         result = C_REXX_CHANG_VOICE;
  769.                         break;
  770.                     case N_MIDI:
  771.                         voice_num 
  772.                         = strtoul(actual_tokens[1].token_str, 
  773.                         (char **)NULL, 10L) - 1;
  774.                         if ((voice_num < MAXVOICE) && (voice_num >= 0))
  775.                         {
  776.                             events[voice_num].nv_i_audio = 0;
  777.                         }
  778.                         result = C_REXX_CHANG_VOICE;
  779.                         break;
  780.                     }
  781.                     break;
  782.                 default:
  783.                 /*
  784.                 ** This was an illegally formatted command, so we should
  785.                 ** return an error code
  786.                 */
  787.                 break;
  788.         }
  789.         if (N_SCALE == (token_accum & M_MENU))
  790.         {
  791.             temp_num = ((token_accum & 0XFF0) >> 4);
  792.             if (0 == temp_num)
  793.             {
  794.                 transpose_interval
  795.                     = strtoul(actual_tokens[1].token_str, 
  796.                     (char **)NULL, 10L) % 12;
  797.                 transpose_scale(transpose_interval, scale, *range);
  798.             }
  799.             else
  800.             {
  801.                 if ((temp_num > 0) && (temp_num < 22))
  802.                 {
  803.                     *range = install_scale(temp_num, scale);
  804.                     *half_range = *range / 2;
  805.                 }
  806.             }
  807.             /* 0 is tranpose; other is scale */
  808.         } 
  809.         rexx_msg->rm_Result1 = RC_OK;  /* defined in rexx/errors.h */
  810.         if( rexx_msg->rm_Action & RXFF_RESULT )
  811.         {
  812.             rexx_msg->rm_Result2 
  813.                 = (LONG)CreateArgstring(REPLY_STR, REPLY_LEN);
  814.         }
  815.     }
  816.     return result;
  817. }
  818.